import React, {useState, useEffect, useContext, useReducer} from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { useFormik } from "formik";
import { Icon } from '@iconify/react';
import PropTypes from "prop-types";
import _, { filter } from 'lodash';
import { sentenceCase } from 'change-case';

// material
import {
  Card,
  Table,
  Stack,
  Avatar,
  Button,
  Checkbox,
  IconButton,
  TableRow,
  TableBody,
  TableCell,
  Container,
  Typography,
  TableContainer,
  TablePagination,
  Dialog,
  DialogTitle,
  DialogContent,
  TextField,
  DialogActions,
  InputLabel,
  Select,
  MenuItem,
  FormControl,
  Box,
  TableHead,
  TableSortLabel,
  Toolbar,
  OutlinedInput,
  InputAdornment,
  Tooltip,
  Popover,
  FormLabel,
  FormGroup,
  FormControlLabel
} from '@mui/material';

// material-styles
import {styled} from "@mui/material/styles";

// material-lab
import AdapterDateFns from '@mui/lab/AdapterDateFns';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import DatePicker from '@mui/lab/DatePicker';

// material-utils
import {visuallyHidden} from "@mui/utils";

//icons-eva
import plusFill from '@iconify/icons-eva/plus-fill';
import editFill from '@iconify/icons-eva/edit-fill';
import trash2Outline from "@iconify/icons-eva/trash-2-outline";
import searchFill from "@iconify/icons-eva/search-fill";
import trash2Fill from "@iconify/icons-eva/trash-2-fill";
import cloudDownloadOutline from "@iconify/icons-eva/cloud-download-outline";
import settingsOutline from "@iconify/icons-eva/settings-outline";
import roundFilterList from "@iconify/icons-ic/round-filter-list";

// components
import Page from '../../../components/Page';
import Label from '../../../components/Label';
import Scrollbar from '../../../components/Scrollbar';
import SearchNotFound from '../../../components/SearchNotFound';
import { ExportToExcel } from "../../../components/@common/AsyncExportExcel/AsyncExcel";

//utils
import { mockImgAvatar } from '../../../utils/mockImages';

// service
import { fetchAjax, postAjax, putAjax, deleteAjax } from '../../../request';
import { systemUsersService } from '../../../API/system/system-user.service';


// ---------------------------------------------------------------------- //

const RolesContext = React.createContext();

const queryParams = {
  name: '',
  email: '',
  age: 18,
  gender: '',
  fieldBy: 'name',
  field: 'asc'
}

const initialValues = {
  name: '',
  email: '',
  password: '',
  gender: '',
  avatarUrl: '',
  dob: new Date()
}

function reducer(state, action) {
  switch (action.type) {
    case 'SEARCH_FORM':
      return action.data;
    case 'OPEN_DIALOG':
      return action.data;
    default:
      return queryParams;
  }
}


// ---------------------------------------------------------------------- //

const HEAD_CELLS = [
  {
    id: 'checkbox',
    dataIndex: 'checkbox',
    type: 'checkbox',
    label: 'checkbox',
    alignRight: false,
    isDisplay: true,
    customRender: ({ record, isItemSelected, handleSelectItemClick })=>{
      const { id } = record;
      return(
        <Checkbox
            checked={isItemSelected}
            onChange={(event) => handleSelectItemClick(event, id)}
        />
      )
    }
  },
  {
    id: 'id',
    dataIndex: 'id',
    label: 'ID',
    alignRight: false,
    isDisplay: true,
  },
  {
    id: 'name',
    dataIndex: 'name',
    label: 'Name',
    alignRight: false,
    isDisplay: true,
    customRender: ({record})=>{
      const { id, name, avatarUrl } = record;
      return(
        <Stack direction="row" alignItems="center" spacing={2}>
          <Avatar alt={name} src={avatarUrl?avatarUrl:mockImgAvatar(24)} />
          <Typography variant="subtitle2" noWrap>
            <RouterLink to={`${id}`} style={{color: '#212B36'}}>
              {name}
            </RouterLink>
          </Typography>
        </Stack>
      )
    }
  },
  {
    id: 'gender',
    dataIndex: 'gender',
    label: 'Gender',
    alignRight: false,
    isDisplay: true,
    customRender: ({record})=>{
      const { gender } = record;
      const genderMap = new Map([
          ['0', 'Males'],
          ['1', 'Females'],
          ['2', '******'] //Secret
      ]);
      const genderKey = genderMap.get(gender);
      return(
          <Stack direction="row" alignItems="center" spacing={2}>
            <Typography variant="subtitle2" noWrap>
              {genderKey}
            </Typography>
          </Stack>
      )
    }
  },
  {
    id: 'email',
    dataIndex: 'email',
    label: 'Email',
    alignRight: false,
    isDisplay: true,
  },
  {
    id: 'dob',
    dataIndex: 'dob',
    label: 'DOB',
    alignRight: false,
    isDisplay: true,
  },
  {
    id: '',
    dataIndex: 'Action',
    label: 'Action',
    alignRight: false,
    isDisplay: true,
    customRender: ({ record, handleEdit, handleDelete }) => {
      return (
          <>
            <IconButton onClick={() => handleEdit(record)}>
              <Icon icon={editFill} width={24} height={24} />
            </IconButton>
            <IconButton onClick={() => handleDelete(record)}>
              <Icon icon={trash2Outline} width={24} height={24} />
            </IconButton>
          </>
      )
    }
  }
];

// ---------------------------------------------------------------------- //

const RootStyle = styled(Toolbar)(({ theme }) => ({
  height: 96,
  display: 'flex',
  justifyContent: 'space-between',
  padding: theme.spacing(0, 1, 0, 3)
}));
const SearchStyle = styled(OutlinedInput)(({ theme }) => ({
  width: 240,
  transition: theme.transitions.create(['box-shadow', 'width'], {
    easing: theme.transitions.easing.easeInOut,
    duration: theme.transitions.duration.shorter
  }),
  '&.Mui-focused': { width: 320, boxShadow: theme.customShadows.z8 },
  '& fieldset': {
    borderWidth: `1px !important`,
    borderColor: `${theme.palette.grey[500_32]} !important`
  }
}));

// ---------------------------------------------------------------------- //


/* 搜索栏  */
function EnhancedTableToolbar({
    headLabel,
    tableList,
    numSelected,
    onChangeDisplayColums
}) {

  const { state, dispatch } = useContext(RolesContext);

  const [displayEl, setDisplayEl] = useState(null);

  const [excelData, setExcelData] = useState([]);

  const formik = useFormik({
    initialValues: queryParams,
    onSubmit: (values, event) => {
      dispatch({
        type: 'SEARCH_FORM',
        data: { queryParams: values }
      });
    },
  });

  const handleResetFields = () => {
    formik.resetForm()
    dispatch({
      type: 'SEARCH_FORM',
      data: { queryParams }
    });
  }

  const handleClick = (event) => {
    setDisplayEl(event.currentTarget);
  };

  const handleClose = () => {
    setDisplayEl(null);
  };

  const open = Boolean(displayEl);
  const id = open ? 'simple-popover' : undefined;


  useEffect(()=>{
    setExcelData(Array.isArray(tableList) ? _.map(tableList, ({ id, name, email, dob })=>({ id, name, email, dob })) : []);
  }, [tableList])

  return (
      <RootStyle
          sx={{
            ...(numSelected > 0 && {
              color: 'primary.main',
              bgcolor: 'primary.lighter'
            })
          }}
      >
        {numSelected > 0 ? (
            <Typography component="div" variant="subtitle1">
              {numSelected} selected
            </Typography>
        ) : (
            <Box sx={{ minWidth: '80%'}}>
              <form onSubmit={formik.handleSubmit}>

                <SearchStyle
                  name="name"
                  value={formik.values.name}
                  onChange={formik.handleChange}
                  placeholder="Search user..."
                  autoComplete="off"
                  startAdornment={
                    <InputAdornment position="start">
                      <Box component={Icon} icon={searchFill} sx={{ color: 'text.disabled' }} />
                    </InputAdornment>
                  }
                />

                <FormControl sx={{ marginLeft: '1rem', minWidth: '8rem' }}>
                  <InputLabel id="roles-gender-select-label">Gender</InputLabel>
                  <Select
                      labelId="roles-gender-select-label"
                      id="roles-search-gender"
                      label="Gender"
                      name="gender"
                      value={formik.values.gender}
                      onChange={formik.handleChange}
                  >
                    <MenuItem value={`0`} >Male</MenuItem>
                    <MenuItem value={`1`} >Female</MenuItem>
                    <MenuItem value={`2`} >保密</MenuItem>
                  </Select>
                </FormControl>

                <FormControl sx={{ display: 'contents' }}>
                  <Button
                    sx={{ marginLeft: '1rem' }}
                    variant="contained"
                    color="primary"
                    type="submit"
                  >
                    Search
                  </Button>

                  <Button
                    sx={{ marginLeft: '1rem' }}
                    variant="contained"
                    color="primary"
                    onClick={handleResetFields}
                  >
                    Reset
                  </Button>
                </FormControl>
              </form>
            </Box>
        )}

        {numSelected > 0 ? (
            <Tooltip title="Delete">
              <IconButton>
                <Icon icon={trash2Fill} />
              </IconButton>
            </Tooltip>
        ) : (
            <div>
              <>
                <ExportToExcel
                    dataSource={excelData}
                    fileName={`数据源${(new Date()).getTime()}`}
                >
                  <IconButton>
                    <Icon icon={cloudDownloadOutline} />
                  </IconButton>
                </ExportToExcel>

                <Tooltip title="Display column">
                  <IconButton aria-describedby={id} onClick={handleClick}>
                    <Icon icon={settingsOutline} />
                  </IconButton>
                </Tooltip>
                <Popover
                    id={id}
                    open={open}
                    anchorEl={displayEl}
                    onClose={handleClose}
                    anchorOrigin={{
                      vertical: 'bottom',
                      horizontal: 'left',
                    }}
                >
                  <Box sx={{ display: 'flex' }}>
                    <FormControl sx={{ m: 3 }} component="fieldset" variant="standard">
                      <FormLabel component="legend">Show Columns</FormLabel>
                      <FormGroup>
                        {
                          _.map(headLabel, headCell=>((!["checkbox"].includes(headCell?.type)) &&
                            <FormControlLabel
                              key={headCell.id}
                              control={
                              <Checkbox checked={headCell.isDisplay} value={headCell.id} onChange={(event)=>onChangeDisplayColums(event, headCell)} />
                            }
                              label={headCell.label}
                            />
                          ))
                        }
                      </FormGroup>
                    </FormControl>
                  </Box>
                </Popover>
              </>

              <Tooltip title="Filter list">
                <IconButton>
                  <Icon icon={roundFilterList} />
                </IconButton>
              </Tooltip>
            </div>
        )}
      </RootStyle>
  );
}
EnhancedTableToolbar.propTypes = {
  headLabel: PropTypes.array,
  tableList: PropTypes.array,
  numSelected: PropTypes.number,
  onChangeDisplayColums: PropTypes.func
};


/* 表头 */
function EnhancedTableHead({
    rowCount,
    headLabel,
    numSelected,
    onRequestSort,
    onSelectAllClick
}) {

  const { state, dispatch } = useContext(RolesContext);

  const { field, fieldBy } = state?.queryParams;

  const createSortHandler = (property) => (event) => {
    property && onRequestSort(event, property);
  };

  return (
      <TableHead>
        <TableRow>
          {headLabel.map((headCell) => {
            return headCell?.type === "checkbox" ? (
              <TableCell key={headCell.id} align={headCell.alignRight ? 'right' : 'left'}>
                <Checkbox
                  indeterminate={numSelected > 0 && numSelected < rowCount}
                  checked={rowCount > 0 && numSelected === rowCount}
                  onChange={onSelectAllClick}
                  inputProps={{ 'aria-label': 'select all role'}}
                />
              </TableCell>
            ) : (headCell.isDisplay &&
              <TableCell
                key={headCell.id}
                align={headCell.alignRight ? 'right' : 'left'}
                sortDirection={fieldBy === headCell.id ? field : false}
              >
                <TableSortLabel
                  hideSortIcon
                  active={fieldBy === headCell.id}
                  direction={fieldBy === headCell.id ? field : 'asc'}
                  onClick={createSortHandler(headCell.id)}
                >
                  {headCell.label}
                  {fieldBy === headCell.id ? (
                    <Box sx={{ ...visuallyHidden }}>
                      {field === 'desc' ? 'sorted descending' : 'sorted ascending'}
                    </Box>
                  ) : null}
                </TableSortLabel>
              </TableCell>
          )})}
        </TableRow>
      </TableHead>
  );
}
EnhancedTableHead.propTypes = {
  field: PropTypes.oneOf(['asc', 'desc']),
  fieldBy: PropTypes.string,
  rowCount: PropTypes.number,
  headLabel: PropTypes.array,
  numSelected: PropTypes.number,
  onRequestSort: PropTypes.func,
  onSelectAllClick: PropTypes.func
};


/* 表 */
function EnhancedTable() {

  const { state, dispatch } = useContext(RolesContext);

  const [tableList, setTableList] = useState([]);
  const [total, setTotal] = useState(10);
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(5);
  const [selected, setSelected] = useState([]);
  const [filterColums, setFilterColums] = useState([...HEAD_CELLS]);

  // 搜索角色
  const queryRoleList = () => {
    console.log('state.queryParams',state.queryParams);
    systemUsersService.ApiSearchUsers({
      offset: page,
      pageSize: rowsPerPage,
      ...state.queryParams
    }).then(res=>{
      const { status, message, data } = res;
      const { content, total } = data;
      if(status === 100 && content){
        setTableList(content);
        setTotal(total)
      }
    });
  }

  const handleEdit = (record)=>{
    dispatch({
      type: 'OPEN_DIALOG',
      data: {
        title: record?.id ? '编辑' :'新增',
        open: true,
        initialValues: record?.id ? record : initialValues
      }
    });
  }

  const handleDelete = async (record)=>{
    const response = await fetch(`/api/system/user/${record.id}`, {
      method: 'DELETE', // *GET, POST, PUT, DELETE, etc.
      mode: 'cors', // no-cors, *cors, same-origin
      cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
      credentials: 'same-origin', // include, *same-origin, omit
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: 'follow', // manual, *follow, error
      referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      // body: JSON.stringify({ userId: record.id  }) // body data type must match "Content-Type" header
    });
    console.log(response.json())
  }

  const handleSelectAllClick = (event) => {
    if (event.target.checked) {
      const newSelecteds = tableList.map((n) => n.id);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  const handleSelectItemClick = (event, id) => {
    const selectedIndex = selected.indexOf(id);
    let newSelected = [];
    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, id);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
          selected.slice(0, selectedIndex),
          selected.slice(selectedIndex + 1)
      );
    }
    setSelected(newSelected);
  };

  const handleChangePage = (event, newPage) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (event) => {
    setRowsPerPage(event.target.value);
    setPage(0);
  };

  const handleFilterByColums = ({ target: { value, checked } }, { isDisplay }) => {
    if(checked){
      setFilterColums(_.map(filterColums, colum=>{
        if([value].includes(colum.id)) colum.isDisplay = true;
        return colum;
      }));
    }else{
      setFilterColums(_.map(filterColums, colum=>{
        if([value].includes(colum.id)) colum.isDisplay = false;
        return colum;
      }));
    }
  };

  const handleRequestSort = (event, property) => {
    const isAsc = (state?.queryParams?.fieldBy === property) && (state?.queryParams?.field === 'asc');
    dispatch({
      type: 'SEARCH_FORM',
      data: {
        queryParams: {
          ...state?.queryParams,
          fieldBy: property,
          field: isAsc ? 'desc' : 'asc'
        }
      }
    });
  };

  const emptyRows = page > 0 ? Math.max(0, rowsPerPage - tableList.length) : 0;

  const isUserNotFound = tableList.length === 0;

  useEffect(()=>{
    state?.queryParams && queryRoleList();
  }, [page, rowsPerPage, state?.queryParams]);


  return (
      <Page title="User | Minimal-UI">
        <Container>
          <Stack direction="row" alignItems="center" justifyContent="space-between" mb={5}>
            <Typography variant="h4" gutterBottom>
              User
            </Typography>
            <Button
                variant="contained"
                startIcon={<Icon icon={plusFill} />}
                onClick={()=>handleEdit({})}
            >
              New User
            </Button>
          </Stack>

          <Card>
            <EnhancedTableToolbar
                headLabel={filterColums}
                tableList={tableList}
                numSelected={selected.length}
                onChangeDisplayColums={handleFilterByColums}
            />


            <Scrollbar>
              <TableContainer sx={{ minWidth: 800 }}>
                <Table>
                  <EnhancedTableHead
                      headLabel={filterColums}
                      rowCount={tableList.length}
                      numSelected={selected.length}
                      onRequestSort={handleRequestSort}
                      onSelectAllClick={handleSelectAllClick}
                  />
                  <TableBody>
                    {_.map(tableList, (row) => {
                      const { id } = row;
                      const isItemSelected = selected.indexOf(id) !== -1;

                      return(
                        <TableRow
                            hover
                            key={id}
                            tabIndex={-1}
                            role="checkbox"
                            selected={isItemSelected}
                            aria-checked={isItemSelected}
                        >
                          {
                            _.map(filterColums, (cell, idx) => {
                              const { customRender: CustomRender, isDisplay, alignRight } = cell;
                              return isDisplay && (
                                  CustomRender ? (
                                    <TableCell key={Math.random() + idx} align={alignRight ? 'right' : 'left'}>
                                      <CustomRender key={idx} sequence={id} record={row} handleEdit={handleEdit} handleDelete={handleDelete} handleSelectItemClick={handleSelectItemClick} isItemSelected={isItemSelected} />
                                    </TableCell>
                                  ) : (
                                    <TableCell key={Math.random() + idx} align={alignRight ? 'right' : 'left'} scope="row">{row[cell.dataIndex]}</TableCell>
                                  )
                              )
                            })
                          }
                        </TableRow>
                      )
                    })}
                    {emptyRows > 0 && (
                        <TableRow style={{ height: 73 * emptyRows }}>
                          <TableCell colSpan={filterColums.length} />
                        </TableRow>
                    )}
                  </TableBody>
                  {isUserNotFound && (
                    <TableBody>
                      <TableRow>
                        <TableCell align="center" colSpan={filterColums.length} sx={{ py: 3 }}>
                          <SearchNotFound searchQuery={state?.queryParams?.filterName} />
                        </TableCell>
                      </TableRow>
                    </TableBody>
                  )}
                </Table>
              </TableContainer>
            </Scrollbar>

            <TablePagination
                rowsPerPageOptions={[5, 10, 25]}
                component="div"
                count={total}
                rowsPerPage={rowsPerPage}
                page={page}
                onPageChange={handleChangePage}
                onRowsPerPageChange={handleChangeRowsPerPage}
            />
          </Card>
        </Container>
      </Page>
  );
}

/* 新增&编辑 Dialog */
const BuildDialog = ({}) => {


  const { state, dispatch } = useContext(RolesContext);

  const formik = useFormik({
    initialValues: state.initialValues,
    onSubmit: (values, event) => {
      systemUsersService[(!!values.id) ? 'ApiUserUpdate' : 'ApiUserSave'](values).then(res=>{
        console.log('hello',res);
        handleClose();
      });
    },
  });


  const handleFormSubmit = () => {
    formik.handleSubmit()
  }

  const handleClose = () => {
    dispatch({ type: 'OPEN_DIALOG', data: { ...state, open: false, initialValues }});
  }

  useEffect(()=>{
    formik.setValues(state?.initialValues)
  }, [state?.initialValues])

  return (
      <Dialog open={!!state.open} onClose={handleClose}  fullWidth aria-labelledby="user-dialog-title">
        <DialogTitle id="user-dialog-title">{state?.title}</DialogTitle>
        <DialogContent sx={{ pt: '10px !important' }}>
          <form>

            <TextField
              id="user-name"
              sx={{ mb: 2 }}
              fullWidth
              type="text"
              size="small"
              label="User Name"
              name="name"
              value={formik.values?.name || ''}
              onChange={formik.handleChange}
            />

            {
              (!formik.values?.id) &&
              <TextField
                id="user-password"
                sx={{ mb: 2 }}
                fullWidth
                type="text"
                size="small"
                label="Password"
                name="password"
                value={formik.values?.password || ''}
                onChange={formik.handleChange}
              />
            }

            <TextField
              id="user-email"
              sx={{ mb: 2 }}
              fullWidth
              type="text"
              size="small"
              label="Email"
              name="email"
              value={formik.values?.email || ''}
              onChange={formik.handleChange}
            />

            <FormControl fullWidth size="small">
              <InputLabel id="user-gender-outlined">Gender</InputLabel>
              <Select
                  labelId="user-gender-outlined"
                  id="user-gender"
                  sx={{ mb: 2 }}
                  label="Gender"
                  name="gender"
                  value={formik.values?.gender || ''}
                  onChange={formik.handleChange}
              >
                <MenuItem value={`0`}>男</MenuItem>
                <MenuItem value={`1`}>女</MenuItem>
                <MenuItem value={`2`}>保密</MenuItem>
              </Select>
            </FormControl>

            <LocalizationProvider dateAdapter={AdapterDateFns}>
              <DatePicker
                  sx={{ mb: 2 }}
                  label="Dob"
                  name="dob"
                  value={formik.values?.dob || ''}
                  onChange={(newValue) => {
                    formik.setFieldValue('dob', newValue)
                  }}
                  renderInput={(params) => <TextField size="small" fullWidth {...params} />}
              />
            </LocalizationProvider>

          </form>
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose}>取消</Button>
          <Button onClick={handleFormSubmit} autoFocus>
            提交
          </Button>
        </DialogActions>
      </Dialog>
  );
}

export default function Roles() {

  const [state, dispatch] = useReducer(reducer, { queryParams });

  return (
      <RolesContext.Provider value={{ state, dispatch }}>
        <EnhancedTable />

        <BuildDialog />
        {/*{
          state.open &&
          <BuildDialog />
        }*/}
      </RolesContext.Provider>
  );
}
